package com.huawei.frs.demo;

import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.core.region.Region;
import com.huaweicloud.sdk.frs.v2.FrsClient;
import com.huaweicloud.sdk.frs.v2.model.*;
import com.huaweicloud.sdk.frs.v2.region.FrsRegion;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Demo {

    private static final Logger LOGGER = LoggerFactory.getLogger(Demo.class.getName());

    public static String getImgStr(String imgPath) {
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            int read = in.read(data);
            LOGGER.debug(String.format("data read : %s", read));
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage());
                }
            }
        }
        return Base64.encodeBase64String(data);
    }

    public static void main(String[] args) {
        // 替换为真实的AK SK
        String ak = "Qa2**************QdV";
        String sk = "aBD**********************************cRv";

        // 获取resources下的文件路径（使用时，需要替换为真实的文件）
        URL faceFile = Demo.class.getClassLoader().getResource("data/face-demo.jpg");
        URL videoFile = Demo.class.getClassLoader().getResource("data/video.mp4");

        // 将图片转为base64
        String imageBase64 = getImgStr(faceFile.getPath());
        String videoBase64 = getImgStr(videoFile.getPath());

        // Init Auth Info
        ICredential credential = getCredential(ak, sk);

        // create frsClient
        FrsClient client = getclient(FrsRegion.CN_NORTH_4, credential);

        // 静默活体检测Base64方式
        detectLiveFaceByBase64(client, imageBase64);

        // 动作活体检测
        String actions = "3";
        detectLiveByBase64(client, actions, videoBase64);

        // 人脸检测Base64方式
        String attributes = "2,4";
        detectFaceByBase64(client, imageBase64, attributes);

        // 人脸比对Base64方式
        compareFaceByBase64(client, imageBase64, imageBase64);

        // 创建人脸集
        String faceSetName = "faceSetName";
        createFaceSet(client, faceSetName);

        // 查询指定人脸集
        showFaceSet(client, faceSetName);

        // 查询所有人脸集
        showAllFaceSets(client);

        // 添加人脸Base64方式
        FaceSetFace faceSetFace = addFacesByBase64(client, faceSetName, imageBase64);
        // 获取face_id
        String faceId = faceSetFace.getFaceId();

        // 人脸搜索Base64方式
        searchFaceByBase64(client, faceSetName, imageBase64);

        // 根据人脸ID更新人脸
        updateFace(client, faceSetName, faceId);

        // 根据人脸ID删除人脸
        deleteFaceByFaceId(client, faceSetName, faceId);

        // 删除人脸集
        deleteFaceSet(client, faceSetName);
    }

    public static ICredential getCredential(String ak, String sk) {
        return new BasicCredentials().withAk(ak).withSk(sk);
    }

    public static FrsClient getclient(Region region, ICredential auth) {
        HttpConfig config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);
        return FrsClient.newBuilder().withCredential(auth).withRegion(region).withHttpConfig(config).build();
    }

    private static void detectLiveFaceByBase64(FrsClient client, String imageBase64) {
        DetectLiveFaceByBase64Request request = new DetectLiveFaceByBase64Request();
        LiveDetectFaceBase64Req body = new LiveDetectFaceBase64Req();
        body.withImageBase64(imageBase64);
        request.withBody(body);
        try {
            DetectLiveFaceByBase64Response response = client.detectLiveFaceByBase64(request);
            System.out.println(response.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void detectFaceByBase64(FrsClient client, String imageBase64, String attributes) {
        DetectFaceByBase64Request detectRequest = new DetectFaceByBase64Request();
        FaceDetectBase64Req faceDetectBase64Req = new FaceDetectBase64Req();
        faceDetectBase64Req.withImageBase64(imageBase64);
        faceDetectBase64Req.withAttributes(attributes);
        detectRequest.setBody(faceDetectBase64Req);
        try {
            DetectFaceByBase64Response detectResponse = client.detectFaceByBase64(detectRequest);
            System.out.println(detectResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void compareFaceByBase64(FrsClient client, String image1_base64, String image2_base64) {
        CompareFaceByBase64Request compareRequest = new CompareFaceByBase64Request();
        FaceCompareBase64Req faceCompareBase64Req = new FaceCompareBase64Req();
        faceCompareBase64Req.withImage1Base64(image1_base64);
        faceCompareBase64Req.withImage2Base64(image2_base64);
        compareRequest.withBody(faceCompareBase64Req);
        try {
            CompareFaceByBase64Response compareResponse = client.compareFaceByBase64(compareRequest);
            System.out.println(compareResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void searchFaceByBase64(FrsClient client, String faceSetName, String imageBase64) {
        SearchFaceByBase64Request searchRequest = new SearchFaceByBase64Request();
        searchRequest.withFaceSetName(faceSetName);
        FaceSearchBase64Req faceSearchBase64Req = new FaceSearchBase64Req();
        List<Map<String, String>> listbodySort = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("timestamp", "asc");
        listbodySort.add(map);
        List<String> listbodyReturnFields = new ArrayList<>();
        listbodyReturnFields.add("timestamp");
        faceSearchBase64Req.withSort(listbodySort);
        faceSearchBase64Req.withReturnFields(listbodyReturnFields);
        faceSearchBase64Req.withImageBase64(imageBase64);
        searchRequest.withBody(faceSearchBase64Req);
        try {
            SearchFaceByBase64Response searchResponse = client.searchFaceByBase64(searchRequest);
            System.out.println(searchResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void createFaceSet(FrsClient client, String faceSetName) {
        CreateFaceSetRequest createFaceSetRequest = new CreateFaceSetRequest();
        CreateFaceSetReq createFaceSetReq = new CreateFaceSetReq();
        createFaceSetReq.withFaceSetName(faceSetName);
        Map<String, TypeInfo> stringTypeInfoMap = new HashMap<>();
        TypeInfo typeInfo = new TypeInfo();
        typeInfo.withType("long");
        stringTypeInfoMap.put("timestamp", typeInfo);
        createFaceSetReq.withExternalFields(stringTypeInfoMap);
        createFaceSetRequest.withBody(createFaceSetReq);
        try {
            CreateFaceSetResponse createFaceSetResponse = client.createFaceSet(createFaceSetRequest);
            System.out.println(createFaceSetResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }

    }

    private static void showFaceSet(FrsClient client, String faceSetName) {
        ShowFaceSetRequest showFaceSetRequest = new ShowFaceSetRequest();
        showFaceSetRequest.withFaceSetName(faceSetName);
        try {
            ShowFaceSetResponse showFaceSetResponse = client.showFaceSet(showFaceSetRequest);
            System.out.println(showFaceSetResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void showAllFaceSets(FrsClient client) {
        ShowAllFaceSetsRequest showAllFaceSetsRequest = new ShowAllFaceSetsRequest();
        try {
            ShowAllFaceSetsResponse showAllFaceSetsResponse = client.showAllFaceSets(showAllFaceSetsRequest);
            System.out.println(showAllFaceSetsResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void deleteFaceSet(FrsClient client, String faceSetName) {
        DeleteFaceSetRequest deleteFaceSetRequest = new DeleteFaceSetRequest();
        deleteFaceSetRequest.withFaceSetName(faceSetName);
        try {
            DeleteFaceSetResponse deleteFaceSetResponse = client.deleteFaceSet(deleteFaceSetRequest);
            System.out.println(deleteFaceSetResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }

    }

    private static FaceSetFace addFacesByBase64(FrsClient client, String faceSetName, String imageBase64) {
        AddFacesByBase64Request addFacesByBase64Request = new AddFacesByBase64Request();
        addFacesByBase64Request.withFaceSetName(faceSetName);
        AddFacesBase64Req addFacesBase64Req = new AddFacesBase64Req();
        addFacesBase64Req.withExternalFields("{\"timestamp\":12}");
        addFacesBase64Req.withImageBase64(imageBase64);
        addFacesByBase64Request.withBody(addFacesBase64Req);
        try {
            AddFacesByBase64Response addFacesByBase64Response = client.addFacesByBase64(addFacesByBase64Request);
            System.out.println(addFacesByBase64Response.toString());
            List<FaceSetFace> faces = addFacesByBase64Response.getFaces();
            return faces.get(0);
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
        return new FaceSetFace();
    }

    private static void deleteFaceByFaceId(FrsClient client, String faceSetName, String faceId) {
        DeleteFaceByFaceIdRequest deleteFaceByFaceIdRequest = new DeleteFaceByFaceIdRequest();
        deleteFaceByFaceIdRequest.withFaceSetName(faceSetName);
        deleteFaceByFaceIdRequest.withFaceId(faceId);
        try {
            DeleteFaceByFaceIdResponse deleteFaceByFaceIdResponse = client.deleteFaceByFaceId(
                deleteFaceByFaceIdRequest);
            System.out.println(deleteFaceByFaceIdResponse.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void updateFace(FrsClient client, String faceSetName, String faceId) {
        UpdateFaceRequest updateFaceRequest = new UpdateFaceRequest();
        updateFaceRequest.withFaceSetName(faceSetName);
        UpdateFaceReq updateFaceReq = new UpdateFaceReq();
        updateFaceReq.withFaceId(faceId);
        updateFaceRequest.withBody(updateFaceReq);
        try {
            UpdateFaceResponse response = client.updateFace(updateFaceRequest);
            System.out.println(response.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }

    private static void detectLiveByBase64(FrsClient client, String actions, String videoBase64) {
        DetectLiveByBase64Request request = new DetectLiveByBase64Request();
        LiveDetectBase64Req body = new LiveDetectBase64Req();
        body.withActions(actions);
        body.withVideoBase64(videoBase64);
        request.withBody(body);
        try {
            DetectLiveByBase64Response response = client.detectLiveByBase64(request);
            System.out.println(response.toString());
        } catch (ConnectionException e) {
            LOGGER.error(e.toString());
        } catch (RequestTimeoutException e) {
            LOGGER.error(e.toString());
        } catch (ServiceResponseException e) {
            LOGGER.error(e.getErrorMsg());
        }
    }
}